package pr.lanmu.config.util;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class ValidUtil {
    public static Object valid(String paramName, String paramValid, String param, List<String> errors) {
        Object paramNameObj = null, paramValidObj = null, paramObj = null;
        if (JSONUtil.isTypeJSON(paramName))
            paramNameObj = JSONUtil.parse(paramName);
        if (JSONUtil.isTypeJSON(paramValid))
            paramValidObj = JSONUtil.parse(paramValid);
        if (JSONUtil.isTypeJSON(param))
            paramObj = JSONUtil.parse(param);
        valid(paramNameObj, paramValidObj, paramObj, StrUtil.EMPTY, errors);
        return paramObj;
    }

    public static Object valid(Object paramName, Object paramValid, Object param, String level, List<String> errors) {
        String paramNameJson = JSONUtil.toJsonStr(paramName);
        if (JSONUtil.isTypeJSONObject(paramNameJson)) {
            dealObject(paramName, paramValid, param, level, errors);
        } else if (JSONUtil.isTypeJSONArray(paramNameJson)) {
            dealArray(paramName, paramValid, param, level, errors);
        } else {
            return dealField(paramName, paramValid, param, level, errors);
        }
        return null;
    }

    private static Object dealField(Object paramName, Object paramValid, Object param, String level, List<String> errors) {
        if (Objects.nonNull(paramName) && Objects.nonNull(paramValid)) {
            ValidBase validBase = JSONUtil.toBean(JSONUtil.toJsonStr(paramValid), ValidBase.class);
            String type = JSONUtil.getByPath(JSONUtil.parse(paramValid), "type")
                    .toString();
            Object val = null;
            boolean flag = true;
            if (Objects.nonNull(param)) {
                try {
                    if (ValidBase.TYPE_BOOLEAN.equalsIgnoreCase(type)) {
                        val = Boolean.parseBoolean(param.toString());
                    } else if (ValidBase.TYPE_NUMBER.equalsIgnoreCase(type)) {
                        val = new BigDecimal(param.toString());
                    } else if (ValidBase.TYPE_STRING.equalsIgnoreCase(type)) {
                        val = param.toString();
                    }
                } catch (Exception e) {
                    flag = false;
                    log.error("类型指定错误，不能转换：{}", e.getMessage());
                    errors.add(String.format("参数：%s | 位置：%s | 错误：类型指定错误", paramName, level));
                }
            }
            if (flag) validBase.valid(val, paramName, level, errors);
            return val;
        }
        return null;
    }

    //对象的处理方案
    private static void dealObject(Object paramName, Object paramValid, Object param, String level, List<String> errors) {
        JSONObject paramNameMap = (JSONObject) paramName;
        JSONObject paramValidMap = (JSONObject) paramValid;
        JSONObject paramMap = (JSONObject) param;
        paramNameMap.forEach((k, v) -> {
            Object obj = paramNameMap.get(k);
            if (Objects.nonNull(paramMap)) {
                Object valid = valid(obj, paramValidMap.get(k), paramMap.get(k), level + "." + k, errors);
                if (Objects.nonNull(valid)) paramMap.set(k, valid);
            } else valid(obj, paramValidMap.get(k), null, level + "." + k, errors);
        });
    }

    //数组的处理方案
    private static void dealArray(Object paramName, Object paramValid, Object param, String level, List<String> errors) {
        JSONArray paramNameList = (JSONArray) paramName;
        JSONArray paramValidList = (JSONArray) paramValid;
        JSONArray paramList = (JSONArray) param;
        AtomicInteger index = new AtomicInteger();
        if (paramNameList.size() > 1) {
            paramNameList.forEach(paramNameObj -> {
                int indexOther = index.get();
                Object paramValidObj;
                Object paramObj = null;
                while (true) {
                    try {
                        paramValidObj = paramValidList.get(indexOther);
                        break;
                    } catch (IndexOutOfBoundsException e) {
                        log.info("校验规则个数对不上");
                        indexOther--;
                    }
                }
                try {
                    paramObj = paramList.get(indexOther);
                } catch (IndexOutOfBoundsException ignored) {
                }
                Object valid = valid(paramNameObj, paramValidObj, paramObj, level + "[" + index + "]", errors);
                if (Objects.nonNull(valid)) paramList.set(index.get(), valid);
                index.getAndIncrement();
            });
        } else {
            if (paramValidList == null) return;
            if (paramList.isEmpty()) {
                paramNameList.forEach(paramNameObj -> {
                    Object paramValidObj = paramValidList.getFirst();
                    Object valid = valid(paramNameObj, paramValidObj, null, level + "[" + index + "]", errors);
                    if (Objects.nonNull(valid)) paramList.set(index.get(), valid);
                    index.getAndIncrement();
                });
            } else {
                paramList.forEach(paramObj -> {
                    Object paramValidObj = paramValidList.getFirst();
                    Object paramNameObj = paramNameList.getFirst();
                    Object valid = valid(paramNameObj, paramValidObj, paramObj, level + "[" + index + "]", errors);
                    if (Objects.nonNull(valid)) paramList.set(index.get(), valid);
                    index.getAndIncrement();
                });
            }
        }
    }
}
